package com.leyou.order.service;

import com.leyou.common.constants.MQConstants;
import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exceptions.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.common.utils.JsonUtils;
import com.leyou.common.utils.UserHolder;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SkuDTO;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.OrderLogistics;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.vo.OrderDetailVO;
import com.leyou.order.vo.OrderLogisticsVO;
import com.leyou.order.vo.OrderVO;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.Exchange.ORDER_EXCHANGE_NAME;
import static com.leyou.common.constants.MQConstants.RoutingKey.ORDER_DELETE_KEY;

/**
 * @author xiuer
 * @description
 * @create 2019/7/13 19:25
 */
@Service
@Slf4j
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper detailMapper;
    @Autowired
    private OrderLogisticsMapper logisticsMapper;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private UserClient userClient;
    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 新增订单
     *
     * @param orderDTO
     * @return
     */
    @Transactional
    public Long insertOrder(OrderDTO orderDTO) {
        try {
            //1.新增订单
            Order order = new Order();
            //设置订单编号
            long orderId = idWorker.nextId();
            order.setOrderId(orderId);
            //订单用户信息 用户id
            Long uid = UserHolder.getUserInfo().getId();
            order.setUserId(uid);
            //设置订单状态
            order.setStatus(1);
            //设置邮费
            order.setPostFee(0L);
            //商品金额相关
            List<CartDTO> carts = orderDTO.getCarts();//页面传来只有数量和skuId
            /*处理CartDTO为一个map， 其key是skuId；值是num 商品数量*/
            Map<Long, Integer> numCartMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
            /*获取所有的skuIds*/
            List<Long> skuIds = orderDTO.getCarts().stream().map(CartDTO::getSkuId).collect(Collectors.toList());
            /*获取所有的商品信息*/
            List<SkuDTO> list = itemClient.querySkuByIds(skuIds);
            /*调用其他微服务接口查询优惠信息（没有不做）*/
            /*计算总金额*/
            /*定义一个Orderdetail 准备批量新增*/
            List<OrderDetail> details = new ArrayList<>();
            long totalPrice = 0;
            for (SkuDTO skuDTO : list) {
                Integer num = numCartMap.get(skuDTO.getId());
                totalPrice += skuDTO.getPrice() * num;//根据skuId 获取购物车中商品的数量
                //2.新增订单详情
                //根据skuId 去查询sku集合，封装到orderDetail中
                // 组装OrderDetail
                OrderDetail detail = new OrderDetail();
                detail.setOrderId(orderId);
                detail.setImage(StringUtils.substringBefore(skuDTO.getImages(), ","));
                detail.setNum(num);
                detail.setSkuId(skuDTO.getId());
                detail.setOwnSpec(skuDTO.getOwnSpec());
                detail.setPrice(skuDTO.getPrice());
                detail.setTitle(skuDTO.getTitle());
                details.add(detail);
            }
            //设置总金额
            // 1.3.3 填写金额数据
            order.setTotalFee(totalPrice);
            /*设置付款方式*/
            order.setPaymentType(orderDTO.getPaymentType());
            /*设置实付金额 ,/* - 优惠金额,=不做*/
            order.setActualFee(totalPrice + order.getPostFee());
            // 写入order表中
            int affectRows = orderMapper.insertSelective(order);
            if (affectRows != 1) {
                throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
            }
            //写入orderDetail表
            affectRows = detailMapper.insertList(details);
            if (affectRows != details.size()) {
                throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
            }
            //3.新增物流信息

            //根据adressId去查询物流信息，封装到orderLogistics
            AddressDTO addressDTO = userClient.queryAddressById(uid, orderDTO.getAddressId());
            //写入表中
            OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
            orderLogistics.setOrderId(orderId);
            affectRows = logisticsMapper.insertSelective(orderLogistics);
            if (affectRows != 1) {
                throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
            }

            itemClient.minusStock(numCartMap);
            /*订单创建完成发送MQ*/
            //定义消息体 skuIds
            Map<String, Object> MQmaps = new HashMap<>();
            MQmaps.put("uid", uid);
            MQmaps.put("skuIds", skuIds);
            amqpTemplate.convertAndSend(ORDER_EXCHANGE_NAME, ORDER_DELETE_KEY, MQmaps);
            log.info("【订单微服务】消息已发送 {}", skuIds.toString());


            return orderId;
        } catch (Exception e) {
            log.error("【订单微服务】创建订单出现 原因{} ", e.getMessage(), e);
            throw new LyException(ExceptionEnum.ORDER_CREATE_FAILED);
        }
    }


    /**
     * 查询订单
     */
    public OrderVO queryOrderByOrderId(Long orderId) {

        try {
            /*查询订单*/
            Order order = orderMapper.selectByPrimaryKey(orderId);
            if (order == null) {
                throw new LyException(ExceptionEnum.ORDER_DETAIL_NOT_FOUND);
            }
            OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);
            /*查询订单详情*/
            OrderDetail record = new OrderDetail();
            record.setOrderId(orderId);
            List<OrderDetail> details = detailMapper.select(record);
            if (CollectionUtils.isEmpty(details)) {
                throw new LyException(ExceptionEnum.ORDER_DETAIL_NOT_FOUND);
            }
            orderVO.setDetailList(BeanHelper.copyWithCollection(details, OrderDetailVO.class));
            /*查询地址*/
            OrderLogistics logistics = logisticsMapper.selectByPrimaryKey(orderId);
            if (logistics == null) {
                throw new LyException(ExceptionEnum.ORDER_DETAIL_NOT_FOUND);
            }
            orderVO.setLogistics(BeanHelper.copyProperties(logistics, OrderLogisticsVO.class));
            log.info("【订单微服务】 订单查询成功{}", orderVO.toString());
            return orderVO;
        } catch (LyException e) {
            log.error("【订单微服务】 订单查询失败 原因{}", e.getMessage(), e);
            throw new RuntimeException("订单查询失败");
        }
    }
}
